package cn.drh.charging.order.rabbitmq;


import cn.drh.charging.order.config.RabbitMQConfiguration;
import cn.drh.charging.order.constant.OrderStatusConstant;
import cn.drh.charging.order.dao.repository.OrderRepository;
import cn.drh.charging.order.dao.mapper.OrderSuccessMapper;
import cn.drh.charging.order.pojo.po.ChargingBillSuccessPO;
import cn.drh.charging.order.pojo.po.OrderMQPO;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * @ClassName RabbitMQOrderConsumer
 * @Description TODO
 * @Author renhong~Deng
 * @Date 2025/6/4 10:55
 * @Version 1.0
 * rabbitmq死信队列消费器
 */

@Slf4j
@Component
public class RabbitMQOrderConsumer {

//    @Autowired
//    private OrderSuccessMapper orderSuccessMapper;
    @Autowired
    private OrderRepository orderRepository;

    /**
     * @ RabbitListener 类似与 我们写的回调类 RabbitMQTests#subscribe DeliverCallback
     * 只需给 @RabbitListener 注解 加上我们要监听的队列,死信队列
     * 当死信队列里有消息的时候,会调用consumeOrderDeadLetter
     * @param orderMQPO 订单号 用于mq与服务之间的流转
     * @param message 消息
     * @param channel 通道
     */
    @RabbitListener(queues = RabbitMQConfiguration.DEAD_LETTER_QUEUE_NAME)
    public void consumeOrderDeadLetter(OrderMQPO orderMQPO, Message message, Channel channel) throws IOException {
        log.debug("消费死信队列消息:{}",orderMQPO);
        //把正在充电中的订单数据的状态修改为 异常结束
        //update charging_bill_success set bill_status = 3
        // where bill_id = orderNo and bill_status = 1
        //2 to two
        orderRepository.updateOrderStatusFromProcess2ExceptionEnd(orderMQPO.getOrderNo());

        //1 用了rabbitmq了么？用了
        //2 怎么用的，解决了什么业务问题？  通过死信队列实现延迟消息，处理超时订单 因为设备故障导致订单状态一直是充电中订单数据
        //3 你的消息能丢失么？不能
        //4 如何保证消息不丢失
        //        生产者 --->  消息队列（RabbitMQ） ---->  消费者
        //      1 生产者不能丢，要保证消息成功的发送到消息队列，消息队列告诉生产者 消息我已经收到了  confirm机制  确认机制
        //      2 消息队列不能丢 durable 把queue 和 exchange durable设置为true 开启持久化
//      //      3 消费者不能丢 关闭自动ack ，手动ack
        //5这样就不会丢了么？会  因为消息队列如果部署的是单机，单点故障，持久化是指持久化到磁盘 磁盘坏了消息回复不了，消息丢失
        //6 rabbitmq  集群是怎么实现的
        //


        //消费队列中的ack是什么意思？
        //consumeChargingDeadLetterQueue 消费者 从RabbitMQ拿到消息 处理业务  更新订单状态
//        正常情况
//                更新订单状态成功，返回ack给消息队列
//                消息队列收到消费者发送的ack后，认为消费者消费消息成功，会把这条消息从消息队列中删除，消费者可以继续消费下一条消息
//        异常情况
//                更新订单状态，数据库出现异常 更新失败，不返回ack给消息队列
//                消息队列没有收到消费者给的ack，认为消费者消费消息失败，不会删除这条消息，会一直保存
//                等数据库恢复了，继续重新消费这条消息，消息没丢，继续更新订单的状态


        //手动ack
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        channel.basicAck(deliveryTag,true);


    }
}
